//+------------------------------------------------------------------+
//|                                  TripleMA_ADX_Strategy.mq5 |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "4.00"
#include <Trade\Trade.mqh>
//--- 输入参数
input int      MAPeriod1 = 10;       // 短期MA周期
input int      MAPeriod2 = 20;       // 中期MA周期
input int      MAPeriod3 = 50;       // 长期MA周期
input int      ADXPeriod = 14;       // ADX计算周期
input double   ADXThreshold = 25.0;  // ADX趋势阈值
input ENUM_MA_METHOD MAMethod = MODE_SMA;
input ENUM_APPLIED_PRICE MAPrice = PRICE_CLOSE;
input double   LotSize = 0.1;
input int      StopLossPoints = 100;
input bool     UseTrailingStop = true;

//--- 全局变量
int MA1Handle, MA2Handle, MA3Handle, ADXHandle;
double MA1Buffer[], MA2Buffer[], MA3Buffer[];
double ADXBuffer[], PlusDIBuffer[], MinusDIBuffer[];
datetime lastBarTime;
double highestSinceOpen, lowestSinceOpen;
bool tradingLock = false;

//+------------------------------------------------------------------+
//| 专家初始化函数                                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // 初始化指标句柄
   MA1Handle = iMA(_Symbol, _Period, MAPeriod1, 0, MAMethod, MAPrice);
   MA2Handle = iMA(_Symbol, _Period, MAPeriod2, 0, MAMethod, MAPrice);
   MA3Handle = iMA(_Symbol, _Period, MAPeriod3, 0, MAMethod, MAPrice);
   ADXHandle = iADX(_Symbol, _Period, ADXPeriod);

   // 设置数组为时间序列
   ArraySetAsSeries(MA1Buffer, true);
   ArraySetAsSeries(MA2Buffer, true);
   ArraySetAsSeries(MA3Buffer, true);
   ArraySetAsSeries(ADXBuffer, true);
   ArraySetAsSeries(PlusDIBuffer, true);
   ArraySetAsSeries(MinusDIBuffer, true);

   lastBarTime = 0;
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 专家去初始化函数                                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   IndicatorRelease(MA1Handle);
   IndicatorRelease(MA2Handle);
   IndicatorRelease(MA3Handle);
   IndicatorRelease(ADXHandle);
}


//+------------------------------------------------------------------+
//| 专家Tick函数                                                     |
//+------------------------------------------------------------------+
void OnTick()
{
  
   // 检查新K线
   datetime currentBarTime = iTime(_Symbol, _Period, 0);
   if(currentBarTime == lastBarTime) return;
   lastBarTime = currentBarTime;

   // 获取指标数据
   if(!GetIndicatorData()) return;

   // 生成交易信号
   bool buySignal = GenerateBuySignal();
   bool sellSignal = GenerateSellSignal();

   // 执行交易逻辑
   if((buySignal || sellSignal) && !tradingLock )
   {
      tradingLock = true;
      CTrade trade;
      trade.SetExpertMagicNumber(2023);
      
      if(buySignal)
      {
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double sl = StopLossPoints > 0 ? ask - StopLossPoints * _Point : 0;
         if(trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, LotSize, ask, sl, 0, "MA_ADX_LONG"))
            highestSinceOpen = ask;
      }
      else if(sellSignal)
      {
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double sl = StopLossPoints > 0 ? bid + StopLossPoints * _Point : 0;
         if(trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, LotSize, bid, sl, 0, "MA_ADX_SHORT"))
            lowestSinceOpen = bid;
      }
      tradingLock = false;
   }
    // 处理移动止损
   if(UseTrailingStop)
   {
      TrailingStopHandler();
      return;
   }

}

//+------------------------------------------------------------------+
//| 获取指标数据                                                     |
//+------------------------------------------------------------------+
bool GetIndicatorData()
{
   // 获取MA数据
   if(CopyBuffer(MA1Handle, 0, 0, 3, MA1Buffer) != 3 ||
      CopyBuffer(MA2Handle, 0, 0, 3, MA2Buffer) != 3 ||
      CopyBuffer(MA3Handle, 0, 0, 3, MA3Buffer) != 3)
      return false;

   // 获取ADX数据（+DI和-DI）
   if(CopyBuffer(ADXHandle, 0, 0, 3, ADXBuffer) != 3 ||  // ADX主线
      CopyBuffer(ADXHandle, 1, 0, 3, PlusDIBuffer) != 3 ||  // +DI
      CopyBuffer(ADXHandle, 2, 0, 3, MinusDIBuffer) != 3)  // -DI
      return false;

   return true;
}

//+------------------------------------------------------------------+
//| 生成买入信号                                                     |
//+------------------------------------------------------------------+
bool GenerateBuySignal()
{
   // MA排列条件
   bool maCondition = MA1Buffer[0] > MA2Buffer[0] && 
                     MA2Buffer[0] > MA3Buffer[0] && 
                     MA1Buffer[1] <= MA2Buffer[1];

   // ADX趋势条件
   bool adxCondition = ADXBuffer[0] > ADXThreshold && 
                      PlusDIBuffer[0] > MinusDIBuffer[0];

   return maCondition && adxCondition;
}

//+------------------------------------------------------------------+
//| 生成卖出信号                                                     |
//+------------------------------------------------------------------+
bool GenerateSellSignal()
{
   // MA排列条件
   bool maCondition = MA1Buffer[0] < MA2Buffer[0] && 
                     MA2Buffer[0] < MA3Buffer[0] && 
                     MA1Buffer[1] >= MA2Buffer[1];

   // ADX趋势条件
   bool adxCondition = ADXBuffer[0] > ADXThreshold && 
                      MinusDIBuffer[0] > PlusDIBuffer[0];

   return maCondition && adxCondition;
}

//+------------------------------------------------------------------+
//| 移动止损处理函数                                                 |
//+------------------------------------------------------------------+
void TrailingStopHandler()
{
   CTrade trade;
   trade.SetExpertMagicNumber(2023);
   
   if(!PositionSelect(_Symbol)) return;

   ulong ticket = PositionGetInteger(POSITION_TICKET);
   ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
   double currentSl = PositionGetDouble(POSITION_SL);
   double currentPrice = posType == POSITION_TYPE_BUY ? SymbolInfoDouble(_Symbol, SYMBOL_BID) 
                                                    : SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   double newSl = 0;
   if(posType == POSITION_TYPE_BUY)
   {
      highestSinceOpen = MathMax(highestSinceOpen, currentPrice);
      newSl = NormalizeDouble(highestSinceOpen - StopLossPoints * _Point, _Digits);
   }
   else
   {
      lowestSinceOpen = MathMin(lowestSinceOpen, currentPrice);
      newSl = NormalizeDouble(lowestSinceOpen + StopLossPoints * _Point, _Digits);
   }
   
   if((posType == POSITION_TYPE_BUY && newSl > currentSl + _Point) ||
      (posType == POSITION_TYPE_SELL && newSl < currentSl - _Point))
   {
      if(!trade.PositionModify(ticket, newSl, PositionGetDouble(POSITION_TP)))
         Print("止损修改失败！错误码:", GetLastError());
   }
}